package com.example.util;

import java.io.FileInputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class DSAUtil {
    /**公钥解密，验证
     * @param publickey 公钥
     * @param conent 验证内容
     * @param bytes 私钥加密字符串
     * */
	public static boolean verifier(String publickey, String conent,
			String bytes) {
		try {
			X509EncodedKeySpec spec = new X509EncodedKeySpec(
					hexToBytes(publickey));
			KeyFactory factory = KeyFactory.getInstance("DSA");
			PublicKey publicKey = factory.generatePublic(spec);
			Signature verifier = Signature.getInstance("dsa");
			verifier.initVerify(publicKey);
			verifier.update(conent.getBytes());
			byte[] bs = hexToBytes(bytes);
			boolean res = verifier.verify(bs);
			return res;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
    /**
     * 私钥加密
     * @param privatekey 私钥
     * @param str 加密内容
     * */
	public static String signer(String privatekey, String str) throws Exception {
		PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(hexToBytes(privatekey));
		KeyFactory factory = KeyFactory.getInstance("DSA");
		PrivateKey privateKey = factory.generatePrivate(spec);
		Signature signer = Signature.getInstance("dsa");
		signer.initSign(privateKey, new SecureRandom());
		byte[] message = str.getBytes("UTF-8");
		signer.update(message);
		byte[] signature = signer.sign();
		return bytesToHex(signature);
	}

	public static boolean verifierFile(String pubkeyFile, String conent,
			String bytes) {
		try {
			PublicKey publicKey = LoadPublicKey(pubkeyFile);
			Signature verifier = Signature.getInstance("dsa");
			verifier.initVerify(publicKey);
			verifier.update(conent.getBytes());
			byte[] bs = hexToBytes(bytes);
			boolean res = verifier.verify(bs);
			return res;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	private static byte[] hexToBytes(String str) {
		if (str == null) {
			return null;
		} else if (str.length() < 2) {
			return null;
		} else {
			int len = str.length() / 2;
			byte[] buffer = new byte[len];
			for (int i = 0; i < len; i++) {
				buffer[i] = (byte) Integer.parseInt(
						str.substring(i * 2, i * 2 + 2), 16);
			}
			return buffer;
		}
	}

	public static String signerFile(String keyfile, String s) throws Exception {
		PrivateKey privateKey = LoadPrivateKey(keyfile);
		Signature signer = Signature.getInstance("dsa");
		signer.initSign(privateKey, new SecureRandom());
		byte[] message = s.getBytes("UTF-8");
		signer.update(message);
		byte[] signature = signer.sign();
		return bytesToHex(signature);
	}

	private static PrivateKey LoadPrivateKey(String filename) {
		PrivateKey key = null;
		try {
			FileInputStream fis = new FileInputStream(filename);
			byte[] b = new byte[fis.available()];
			fis.read(b);
			fis.close();
			PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(b);
			KeyFactory factory = KeyFactory.getInstance("DSA");
			key = factory.generatePrivate(spec);
		} catch (Exception e) {
			System.err.println("LoadPrivateKey: " + e.toString());
		}
		return key;
	}

	private static PublicKey LoadPublicKey(String filename) {
		PublicKey key = null;
		try {
			FileInputStream fis = new FileInputStream(filename);
			byte[] b = new byte[fis.available()];
			fis.read(b);
			fis.close();
			X509EncodedKeySpec spec = new X509EncodedKeySpec(b);
			KeyFactory factory = KeyFactory.getInstance("DSA");
			key = factory.generatePublic(spec);
		} catch (Exception e) {
			System.err.println("LoadPublicKey: " + e.toString());
		}
		return key;
	}

	public static String bytesToHex(byte[] data) {
		if (data == null) {
			return null;
		} else {
			int len = data.length;
			String str = "";
			for (int i = 0; i < len; i++) {
				if ((data[i] & 0xFF) < 16)
					str = str + "0"
							+ java.lang.Integer.toHexString(data[i] & 0xFF);
				else
					str = str + java.lang.Integer.toHexString(data[i] & 0xFF);
			}
			return str.toUpperCase();
		}
	}
}
